<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Painting with Cairo in PHP GTK</title>
<link rel="stylesheet" href="/cfg/format.css" type="text/css">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="keywords" content="GUI, GTK, Cairo, drawing, PHP, programming, Linux">
<meta name="description" content="This part of the PHP GTK tutorial covers painting with Cairo.">
<meta name="language" content="en">
<meta name="author" content="Jan Bodnar">
<meta name="distribution" content="global">

<script type="text/javascript" src="/lib/jquery.js"></script>
<script type="text/javascript" src="/lib/common.js"></script>

</head>

<body>

<div class="container">

<div id="wide_ad" class="ltow">
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* 160x600, August 2011 */
google_ad_slot = "2484182563";
google_ad_width = 160;
google_ad_height = 600;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>

<div class="content">


<a href="/" title="Home">Home</a>&nbsp;
<a href="..">Contents</a>


<h1>Painting with Cairo</h1>

<p>
In this part of the PHP GTK tutorial, we will do some painting with the Cairo library.
Currently, Seed supports only a small portion of the Cairo library. 
</p>

<div class="center">
<script type="text/javascript"><!--
google_ad_client = "ca-pub-9706709751191532";
/* top_horizontal */
google_ad_slot = "3327173442";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>

<p>
<b>Cairo</b> is a library for creating 2D vector graphics. 
We can use it to draw our own widgets, charts or various effects or animations. 
</p>

<p>
Cairo for PHP is a separate project from PHP GTK. In addition to PHP GTK, we need
to install Cairo too. Prior to building the library, we must have libcairo2-dev
package installed on our system. 
</p>

<pre>
svn co http://svn.php.net/repository/pecl/cairo/trunk cairo
cd cairo/
$ phpize5
$ ./configure 
$ make
$ make install
</pre>

<p>
The above commands were used to install Cairo for PHP at the time of the creation
of this tutorial. 
</p>

<p>
Finally, after we have installed Cairo, we need to enable Cairo library for 
our PHP scripts. 
</p>

<pre>
$ sudo vi /etc/php5/cli/php.ini 

;;;;;;;;;;;;;;;;;;;;;;
; Dynamic Extensions ;
;;;;;;;;;;;;;;;;;;;;;;

;
extension=php_gtk2.so
extension=cairo.so
</pre>

<p>
We edit the php.ini file and add the Cairo dynamic extension. 
</p>


<h2>Colors</h2>

<p>
In the first example, we will work with colors. A color is an object representing a combination of 
Red, Green, and Blue (RGB) intensity values.
Cairo valid RGB values are in the range 0 to 1. 
</p>

<pre class="code">
&lt;?php
 
/* 
ZetCode PHP GTK tutorial

In this program, we will draw three
colored rectangles on the drawing area
using Cairo.

author: Jan Bodnar
website: www.zetcode.com
last modified: August 2011
*/

class Example extends GtkWindow { 
     

    public function __construct() { 

        parent::__construct(); 
         
        $this-&gt;init_ui();

    } 

    public function init_ui() {

        $this-&gt;set_title('Colors');         
        $this-&gt;connect_simple('destroy', array('gtk', 'main_quit')); 

        $darea = new GtkDrawingArea();
        $darea-&gt;connect('expose_event', array($this, 'on_expose')); 
        
        $this-&gt;add($darea);    

        $this-&gt;set_default_size(360, 100); 
        $this-&gt;set_position(GTK::WIN_POS_CENTER);
        $this-&gt;show_all();         
    }

    public function on_expose($darea, $event) {

            $cr = $darea-&gt;window-&gt;cairo_create();
            $this-&gt;draw_colors($cr);        
   
    }

    public function draw_colors($cr) {
    
        $cr-&gt;setSourceRgb(0.2, 0.23, 0.9);
        $cr-&gt;rectangle(10, 15, 90, 60);
        $cr-&gt;fill();
        
        $cr-&gt;setSourceRgb(0.9, 0.1, 0.1);
        $cr-&gt;rectangle(130, 15, 90, 60);
        $cr-&gt;fill();

        $cr-&gt;setSourceRgb(0.4, 0.9, 0.4);
        $cr-&gt;rectangle(250, 15, 90, 60);
        $cr-&gt;fill();            
    }   
} 
     
new Example(); 
Gtk::main();
 
?&gt;
</pre>

<p>
In our example, we will draw three rectangles and fill them with
three different colors. 
</p>

<pre class="explanation">
$darea = new GtkDrawingArea();
</pre>

<p>
We will be doing our drawing operations on the <code>GtkDrawingArea</code> 
widget. 
</p>

<pre class="explanation">
$darea-&gt;connect('expose_event', array($this, 'on_expose')); 
</pre>

<p>
When the window needs to be redrawn, the 
the <code>expose_event</code> is triggered. In response to this event,
we call the <code>on_expose()</code> method. 
</p>

<pre class="explanation">
$cr = $darea-&gt;window-&gt;cairo_create();
</pre>

<p>
We create the cairo context object from the
<code>GdkWindow</code> of the drawing area. The context is an
object onto which we do all our drawings. 
</p>

<pre class="explanation">
$this-&gt;draw_colors($cr);   
</pre>

<p>
The actual drawing is delegated to the <code>draw_colors()</code> method. 
</p>


<pre class="explanation">
$cr-&gt;setSourceRgb(0.2, 0.23, 0.9);
</pre>

<p>
The <code>setSourceRgb()</code> method sets a color for the 
cairo context. The three parameters of the method are the color intensity
values. 
</p>

<pre class="explanation">
$cr-&gt;rectangle(10, 15, 90, 60);
</pre>

<p>
We draw a rectangle. The first two parameters are the x, y coordinates of the
top left corner of the rectangle. The last two parameters are the width and height
of the rectangle. 
</p>


<pre class="explanation">
$cr-&gt;fill();
</pre>

<p>
We fill the inside of the rectangle with the current color. 
</p>


<img src="/img/gui/phpgtk/colors.png" alt="Colors">
<div class="figure">Figure: Colors</div>


<h2>Basic shapes</h2>

<p>
The next example draws some basic shapes onto the window. 
</p>

<pre class="code">
&lt;?php
 
/* 
ZetCode PHP GTK tutorial

This code example draws basic shapes
with the Cairo library.

author: Jan Bodnar
website: www.zetcode.com
last modified: August 2011
*/

class Example extends GtkWindow { 
     

    public function __construct() { 

        parent::__construct(); 
         
        $this-&gt;init_ui();

    } 

    public function init_ui() {

        $this-&gt;set_title('Basic shapes');         
        $this-&gt;connect_simple('destroy', array('gtk', 'main_quit')); 

        $darea = new GtkDrawingArea();
        $darea-&gt;connect('expose_event', array($this, 'on_expose')); 
        
        $this-&gt;add($darea);    

        $this-&gt;set_default_size(390, 240); 
        $this-&gt;set_position(GTK::WIN_POS_CENTER);
        $this-&gt;show_all();         
    }

    public function on_expose($darea, $event) {

        $cr = $darea-&gt;window-&gt;cairo_create();
        $this-&gt;draw_shapes($cr);        

    }

    public function draw_shapes($cr) {
    
        $cr-&gt;SetSourceRgb(0.6, 0.6, 0.6);

        $cr-&gt;rectangle(20, 20, 120, 80);
        $cr-&gt;rectangle(180, 20, 80, 80);
        $cr-&gt;fill();

        $cr-&gt;arc(330, 60, 40, 0, 2*M_PI);
        $cr-&gt;fill();
        
        $cr-&gt;arc(90, 160, 40, M_PI/4, M_PI);
        $cr-&gt;fill();

        $cr-&gt;translate(220, 180);
        $cr-&gt;scale(1, 0.7);
        $cr-&gt;arc(0, 0, 50, 0, 2*M_PI);
        $cr-&gt;fill();          
    }   
} 
     
new Example(); 
Gtk::main();
 
?&gt;
</pre>

<p>
In this example, we will create a rectangle, a square, a circle, an arc and an ellipse. 
We draw outlines in blue color, insides in white. 
</p>

<pre class="explanation">
$cr-&gt;rectangle(20, 20, 120, 80);
$cr-&gt;rectangle(180, 20, 80, 80);
$cr-&gt;fill();
</pre>

<p>
These lines draw a rectangle and a square. 
</p>

<pre class="explanation">
$cr-&gt;arc(330, 60, 40, 0, 2*M_PI);
$cr-&gt;fill();
</pre>

<p>
Here the <code>arc()</code> method draws a full circle.
</p>

<pre class="explanation">
$cr-&gt;translate(220, 180);
$cr-&gt;scale(1, 0.7);
$cr-&gt;arc(0, 0, 50, 0, 2*M_PI);
$cr-&gt;fill();  
</pre>

<p>
The <code>translate()</code> method moves the object to a specific
point. If we want to draw an oval, we do some scaling first. Here the 
<code>scale()</code> method shrinks the y axis.
</p>


<img src="/img/gui/phpgtk/shapes.png" alt="Basic shapes">
<div class="figure">Figure: Basic shapes</div>



<h2>Transparent rectangles</h2>

<p>
Transparency is the quality of being able to see through a material. The easiest way to understand 
transparency is to imagine a piece of glass or water. Technically, the rays of light can go
through the glass and this way we can see objects behind the glass.
</p>

<p>
In computer graphics, we can achieve transparency effects using alpha compositing. Alpha compositing
is the process of combining an image with a background to create the appearance of partial transparency. 
The composition process uses an alpha channel. (wikipedia.org, answers.com)
</p>

<pre class="code">
&lt;?php
 
/* 
ZetCode PHP GTK tutorial

This code example draws nine rectangles
with different levels of transparency.

author: Jan Bodnar
website: www.zetcode.com
last modified: August 2011
*/

class Example extends GtkWindow { 
     

    public function __construct() { 

        parent::__construct(); 
         
        $this-&gt;init_ui();

    } 

    public function init_ui() {

        $this-&gt;set_title('Transparent rectangles');         
        $this-&gt;connect_simple('destroy', array('gtk', 'main_quit')); 

        $darea = new GtkDrawingArea();
        $darea-&gt;connect('expose_event', array($this, 'on_expose')); 
        
        $this-&gt;add($darea);    

        $this-&gt;set_default_size(590, 90); 
        $this-&gt;set_position(GTK::WIN_POS_CENTER);
        $this-&gt;show_all();         
    }

    public function on_expose($darea, $event) {

        $cr = $darea-&gt;window-&gt;cairo_create();
        $this-&gt;draw_recs($cr);        

    }

    public function draw_recs($cr) {

        for ($i=1; $i&lt;=10; $i++) {
            $cr-&gt;SetSourceRgba(0, 0, 1, $i*0.1);
            $cr-&gt;rectangle(50*$i, 20, 40, 40);
            $cr-&gt;fill();
        }     
    }   
} 
     
new Example(); 
Gtk::main();
 
?&gt;
</pre>

<p>
In the example we will draw ten rectangles with different levels of transparency. 
</p>

<pre class="explanation">
$cr-&gt;SetSourceRgba(0, 0, 1, $i*0.1);
</pre>

<p>
The last parameter of the <code>set_source_rgba()</code> method is the
alpha transparency.
</p>

<img src="/img/gui/phpgtk/trreg.png" alt="Transparent rectangles">
<div class="figure">Figure: Transparent rectangles</div>


<h2>Donut</h2> 
 
<p> 
In the following example we create a complex shape by rotating a bunch of ellipses. 
</p> 
 
<pre class="code"> 
&lt;?php
 
/* 
ZetCode PHP GTK tutorial

In this program, we draw a donut shape
by rotating a bunch of ellipses. 

author: Jan Bodnar
website: www.zetcode.com
last modified: August 2011
*/

class Example extends GtkWindow { 
     

    public function __construct() { 

        parent::__construct(); 
         
        $this-&gt;init_ui();

    } 

    public function init_ui() {

        $this-&gt;set_title('Donut');         
        $this-&gt;connect_simple('destroy', array('gtk', 'main_quit')); 

        $darea = new GtkDrawingArea();
        $darea-&gt;connect('expose_event', array($this, 'on_expose')); 
        
        $this-&gt;add($darea);    

        $this-&gt;set_default_size(350, 250); 
        $this-&gt;set_position(GTK::WIN_POS_CENTER);
        $this-&gt;show_all();         
    }

    public function on_expose($darea, $event) {

            $cr = $darea-&gt;window-&gt;cairo_create();
            $this-&gt;draw_donut($cr);        
   
    }

    public function draw_donut($cr) {
    
        $cr-&gt;SetLineWidth(0.5);

        $w = $this-&gt;get_allocation()-&gt;width;
        $h = $this-&gt;get_allocation()-&gt;height;
       
        $cr-&gt;translate($w/2, $h/2);
        $cr-&gt;arc(0, 0, 120, 0, 2*M_PI);
        $cr-&gt;stroke();
         
        for ($i=1; $i&lt;=36; $i++) {
            $cr-&gt;save();
            $cr-&gt;rotate($i*M_PI/36);
            $cr-&gt;scale(0.3, 1);
            $cr-&gt;arc(0, 0, 120, 0, 2*M_PI);
            $cr-&gt;restore();
            $cr-&gt;stroke();
        }
    }   
} 
     
new Example(); 
Gtk::main();
 
?&gt;
</pre> 
 
<p> 
In this example, we create a donut. The shape resembles a cookie, 
hence the name donut.
</p> 
 
<pre class="explanation">
$cr-&gt;translate($w/2, $h/2);
$cr-&gt;arc(0, 0, 120, 0, 2*M_PI);
$cr-&gt;stroke();
</pre> 
 
<p> 
In the beginning there is an ellipse. 
</p> 
 
<pre class="explanation">
for ($i=1; $i&lt;=36; $i++) {
    $cr-&gt;save();
    $cr-&gt;rotate($i*M_PI/36);
    $cr-&gt;scale(0.3, 1);
    $cr-&gt;arc(0, 0, 120, 0, 2*M_PI);
    $cr-&gt;restore();
    $cr-&gt;stroke();
}
</pre> 
 
<p> 
After several rotations, there is a donut.
</p> 
 
 
<h2>Drawing text</h2> 
 
<p> 
In the next example, we draw some text on the window. 
</p> 
 
<pre class="code">
&lt;?php
 
/* 
ZetCode PHP GTK tutorial

In this program, we draw text on the
window. 

author: Jan Bodnar
website: www.zetcode.com
last modified: August 2011
*/

class Example extends GtkWindow { 
     

    public function __construct() { 

        parent::__construct(); 
         
        $this-&gt;init_ui();

    } 

    public function init_ui() {

        $this-&gt;set_title('Soulmate');         
        $this-&gt;connect_simple('destroy', array('gtk', 'main_quit')); 

        $darea = new GtkDrawingArea();
        $darea-&gt;connect('expose_event', array($this, 'on_expose')); 
        
        $this-&gt;add($darea);    

        $this-&gt;set_default_size(350, 250); 
        $this-&gt;set_position(GTK::WIN_POS_CENTER);
        $this-&gt;show_all();         
    }

    public function on_expose($darea, $event) {

            $cr = $darea-&gt;window-&gt;cairo_create();
            $this-&gt;draw_text($cr);        
   
    }

    public function draw_text($cr) {
    
        $cr-&gt;SetSourceRgb(0.1, 0.1, 0.1);
         
        $cr-&gt;SelectFontFace("Purisa", CairoFontSlant::NORMAL, 
            CairoFontWeight::NORMAL);
        $cr-&gt;SetFontSize(13);
       
        $cr-&gt;MoveTo(20, 30);
        $cr-&gt;ShowText("Most relationships seem so transitory");
        $cr-&gt;MoveTo(20, 60);
        $cr-&gt;ShowText("They're all good but not the permanent one");
        $cr-&gt;MoveTo(20, 120);
        $cr-&gt;ShowText("Who doesn't long for someone to hold");
        $cr-&gt;MoveTo(20, 150);
        $cr-&gt;ShowText("Who knows how to love without being told");
        $cr-&gt;MoveTo(20, 180);
        $cr-&gt;ShowText("Somebody tell me why I'm on my own");
        $cr-&gt;MoveTo(20, 210);
        $cr-&gt;ShowText("If there's a soulmate for everyone");
    }   
} 
     
new Example(); 
Gtk::main();
 
?&gt;
</pre> 
 
<p> 
We display part of the lyrics from the Natasha Bedingfields Soulmate song. 
</p> 
 
<pre class="explanation">
$cr-&gt;SelectFontFace("Purisa", CairoFontSlant::NORMAL, 
    CairoFontWeight::NORMAL);
</pre> 
 
<p> 
Here we specify the font, that we use. Purisa normal.
</p> 
 
<pre class="explanation">
$cr-&gt;SetFontSize(13);
</pre> 
 
<p> 
We specify the size of the font.
</p> 
 
<pre class="explanation">
$cr-&gt;MoveTo(20, 30);
</pre> 
 
<p> 
We move to the point, where we will draw the text. 
</p> 
 
<pre class="explanation">
$cr-&gt;ShowText("Most relationships seem so transitory");
</pre> 
 
<p> 
The <code>ShowText()</code> method draws text onto the window. 
</p> 
 
 
<img src="/img/gui/phpgtk/drawtext.png" alt="Soulmate"> 
<div class="figure">Figure: Soulmate</div> 

<p>
In this chapter of the PHP GTK tutorial, we were painting 
with Cairo library.
</p>


<div class="center"> 
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* horizontal */
google_ad_slot = "1734478269";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script> 
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> 
</script> 
</div> 
<br>


<div class="botNav, center">
<span class="botNavItem"><a href="/">Home</a></span> ‡ <span class="botNavItem"><a href="..">Contents</a></span> ‡ 
<span class="botNavItem"><a href="#">Top of Page</a></span>
</div>


<div class="footer">
<div class="signature">
<a href="/">ZetCode</a> last modified September 4, 2011  <span class="copyright">&copy; 2007 - 2013 Jan Bodnar</span>
</div>
</div>

</div> <!-- content -->

</div> <!-- container -->

</body>
</html>
